package jmu.edu.yjc.service.answer;

import jmu.edu.yjc.Utils.RedisCache;
import jmu.edu.yjc.domain.entity.neo4j.RelationEntity.HasSymptom;
import org.ahocorasick.trie.Emit;
import org.ahocorasick.trie.Trie;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Consumer;
//人工智能的本致也是迭代数据集
@Component
public class QuestionClassifier {
    @Resource
    private RedisCache redisCache;
    private static RedisCache REDIS_CACHE;
    //acTree 加速输入的问句过滤
    public static Trie acTree;
    public static Trie.TrieBuilder builder;
    public static HashMap<String,String> word_dict;
    public static BufferedReader reader;
    public volatile static List<String> symptom_qwds ;
    public volatile static List<String> cause_qwds ;
    public volatile static List<String> acompany_qwds ;
    public volatile static List<String> food_qwds ;
    public volatile static List<String> drug_qwds ;
    public volatile static List<String> prevent_qwds ;
    public volatile static List<String> lasttime_qwds;
    public volatile static List<String> cureprob_qwds ;
    public volatile static List<String> cureway_qwds ;
    public volatile static List<String> easyget_qwds ;
    public volatile static List<String> check_qwds ;
    public volatile static List<String> belong_qwds ;
    public volatile static List<String> cure_qwds ;
    public volatile static List<String> deny_words;
    @PostConstruct
    public void init(){
        REDIS_CACHE = this.redisCache;
        initResource();
        initKeywords();
    }
    public synchronized static void initKeywords(){
        symptom_qwds = REDIS_CACHE.getCacheObject("symptom_qwds");
        cause_qwds = REDIS_CACHE.getCacheObject("cause_qwds");
        acompany_qwds = REDIS_CACHE.getCacheObject("acompany_qwds");
        food_qwds = REDIS_CACHE.getCacheObject("food_qwds");
        drug_qwds = REDIS_CACHE.getCacheObject("drug_qwds");
        prevent_qwds = REDIS_CACHE.getCacheObject("prevent_qwds");
        lasttime_qwds = REDIS_CACHE.getCacheObject("lasttime_qwds");
        cureprob_qwds = REDIS_CACHE.getCacheObject("cureprob_qwds");
        cureway_qwds = REDIS_CACHE.getCacheObject("cureway_qwds");
        easyget_qwds = REDIS_CACHE.getCacheObject("easyget_qwds");
        check_qwds = REDIS_CACHE.getCacheObject("check_qwds");
        belong_qwds = REDIS_CACHE.getCacheObject("belong_qwds");
        cure_qwds = REDIS_CACHE.getCacheObject("cure_qwds");
        deny_words = REDIS_CACHE.getCacheObject("deny_words");
    }
    /**
     * @description: 初始化，构建ACTree加速问题过滤出关键词
     * @param:
     * @return: void
     * @author yjc
     * @date: 2023/3/12 1:04
     */
    public static void initResource(){
        List<TypeResource> resourceList = Arrays.asList(new TypeResource(new ClassPathResource("static/dict/check.txt"),"check"),
                new TypeResource(new ClassPathResource("static/dict/symptom.txt"),"symptom"),new TypeResource(new ClassPathResource("static/dict/department.txt"),"department"),
                new TypeResource(new ClassPathResource("static/dict/disease.txt"),"disease"),new TypeResource(new ClassPathResource("static/dict/drug.txt"),"drug"),
                new TypeResource(new ClassPathResource("static/dict/food.txt"),"food"),new TypeResource(new ClassPathResource("static/dict/producer.txt"),"producer"));
        word_dict = new HashMap<>();
        List<String> keyWords = new ArrayList<>();
        resourceList.forEach(resource -> {
            try {
                reader = new BufferedReader(new InputStreamReader(resource.getResource().getInputStream(),StandardCharsets.UTF_8));
                String line = reader.readLine();
                while (line!=null){
                    word_dict.put(line,resource.getType());
                    keyWords.add(line);
                    line = reader.readLine();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        builder = Trie.builder().ignoreOverlaps().addKeywords(keyWords);
        acTree =  builder.build();
    }
    public static void IncrementalBuild(Set<String> keywords, String type){
        for (String keyword : keywords) {
            word_dict.put(keyword, type);
        }
        builder.addKeywords(keywords);
        acTree = builder.build();
    }
    /***
     * @description: 获取到问题的分类
     * @param: question
     * @return: ClassifierResult
     * @author yjc
     * @date: 2023/3/12 1:04
     */
    public ClassifierResult getQuestionClassifier(String question){
        ClassifierResult classifier = new ClassifierResult();
        Map<String,String> final_dict = check_medical(question);
        classifier.setDict(final_dict);
        List<String> types = new ArrayList<>(final_dict.values());
        List<String> questionTypes = new ArrayList<>();
        String questionType = "others";
        //跟疾病相关
        if(types.contains("disease")){
            //症状
            if(check_words(symptom_qwds, question)){
                questionType = "disease_symptom";
                questionTypes.add(questionType);
            }
            //原因
            if(check_words(cause_qwds,question)){
                questionType = "disease_cause";
                questionTypes.add(questionType);
            }
            //并发症
            if(check_words(acompany_qwds,question)){
                questionType = "disease_acompany";
                questionTypes.add(questionType);
            }
            //食品
            if(check_words(food_qwds,question)){
                boolean is_deny = check_words(deny_words,question);
                if(is_deny){
                    questionType = "disease_not_food";
                }else {
                    questionType = "disease_do_food";
                }
                questionTypes.add(questionType);
            }
            //药品
            if(check_words(drug_qwds,question)){
                questionType = "disease_drug";
                questionTypes.add(questionType);
            }
            //疾病接受检查项目
            if(check_words(check_qwds,question)){
                questionType = "disease_check";
                questionTypes.add(questionType);
            }
            //疾病预防
            if(check_words(prevent_qwds,question)){
                questionType = "disease_prevent";
                questionTypes.add(questionType);
            }
            //疾病医疗周期
            if(check_words(lasttime_qwds,question)){
                questionType = "disease_lasttime";
                questionTypes.add(questionType);
            }
            //疾病治疗方式
            if(check_words(cureway_qwds,question)){
                questionType = "disease_cureway";
                questionTypes.add(questionType);
            }
            //疾病治愈可能性
            if(check_words(cureprob_qwds,question)){
                questionType = "disease_cureprob";
                questionTypes.add(questionType);
            }
            //疾病易感染人群
            if(check_words(easyget_qwds,question)){
                questionType = "disease_easyget";
                questionTypes.add(questionType);
            }
        }
        if(check_words(symptom_qwds, question)&&types.contains("symptom")){
            questionType = "symptom_disease";
            questionTypes.add(questionType);
        }
        //已知食物找疾病
        if(types.contains("food")&&(check_words(food_qwds,question)||check_words(cure_qwds,question))){
            boolean is_deny = check_words(deny_words,question);
            if(is_deny){
                questionType = "food_not_disease";
            }else {
                questionType = "food_do_disease";
            }
            questionTypes.add(questionType);
        }
        //已经知道药品查疾病
        if(types.contains("drug")&&check_words(cure_qwds,question)){
            questionType = "drug_disease";
            questionTypes.add(questionType);
        }
        //已经知道检查项目查疾病
        if(types.contains("check")&&(check_words(cure_qwds,question)||check_words(check_qwds,question))){
            questionType = "check_disease";
            questionTypes.add(questionType);
        }
        //若没有查到相关的外部查询信息，那么则将该疾病的描述信息返回
        if(questionTypes.size() == 0 && types.contains("disease")){
            questionTypes.add("disease_desc");
        }
        //若没有查到相关的外部查询信息，那么则将该疾病的描述信息返回
        if(questionTypes.size() == 0 && types.contains("symptom")){
            questionTypes.add("symptom_disease");
        }
        classifier.setQuestionTypes(questionTypes);
        return classifier;
    }
    /**
     * @description: 根据actree搜出来的关键字匹配字典
     * @param: question
     * @return: Map<String,String>
     * @author yjc
     * @date: 2023/3/12 1:05
     */
    private Map<String,String> check_medical(String question){
        Collection<Emit> emits = acTree.parseText(question);
        List<String> words = new ArrayList<>();
        emits.forEach(emit -> words.add(emit.getKeyword()));
        Map<String,String> final_dict = new HashMap<>();
        words.forEach(word -> {
            final_dict.put(word,word_dict.get(word));
        });
        return final_dict;
    }
    /***
     * @description: 检查问题是否在静态关键字数组里
     * @param: qwds     question
     * @return: boolean
     * @author yjc
     * @date: 2023/3/12 1:06
     */
    private boolean check_words(List<String> qwds,String question){
        for (String qwd : qwds) {
            if(question.contains(qwd)){
                return true;
            }
        }
        return false;
    }
}
